import {resetRouter} from '@/router'
import {getSession, getCookie} from '@/utils/auth'

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
  const res = []

  routes.forEach(route => {
    const tmp = {...route}
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}

// 路由懒加载
export const _import = (filePath) => {
  // return (resolve) => require([`@/views/${filePath}.vue`], resolve)
  return (resolve) => import(`@/views/${filePath}`).then((res) => {
    resolve(res)
  }).catch(() => import(`@/views/Err404.vue`))
}

export const _importAttr = (filePath, attr) => { // 路由懒加载
  let str = filePath.replace('@/views/', '')
  const component = require('@/views/' + str)
  if (attr === 'aside') {
    return component.default.aside || ''
  } else {
    return component.default[attr] || ''
  }
}

/**
 * 动态路由添加组件
 * @param routes asyncRoutes
 * @param roles
 */
export function compAsyncRoutes(routes, roles = 'admin') {
  return routes.filter(route => {
    if (route.menuComponet) {
      route.components = {
        default: _import(route.menuComponet),
        aside: route.aside ? _import('comp/CompAside') : '',
        topaside: route.aside ? _import('comp/TopAside') : '',

      }
    }
    route.path = route.menuUrl
    if (route.child && route.child.length) {
      route.children = compAsyncRoutes(route.child)
    } else {
      delete route.child
    }
    return route.menuUrl
  })
}

export function deepClone(target) {
  // 定义一个变量
  let result
  // 如果当前需要深拷贝的是一个对象的话
  if (typeof target === 'object') {
    // 如果是一个数组的话
    if (Array.isArray(target)) {
      // 将result赋值为一个数组，并且执行遍历
      result = []
      for (let i in target) {
        // 递归克隆数组中的每一项
        result.push(deepClone(target[i]))
      }
      // 判断如果当前的值是null的话；直接赋值为null
    } else if (target === null) {
      result = null
      // 判断如果当前的值是一个RegExp对象的话，直接赋值
    } else if (target.constructor === RegExp) {
      result = target
    } else {
      // 否则是普通对象，直接for in循环，递归赋值对象的所有值
      result = {}
      for (let i in target) {
        result[i] = deepClone(target[i])
      }
    }
    // 如果不是对象的话，就是基本数据类型，那么直接赋值
  } else {
    result = target
  }
  // 返回最终结果
  return result
}

// 将多层嵌套路由处理成平级
function flatAsyncRoutes(routes, breadcrumb, baseUrl = '', activeNav, aside = [], level) {
  let res = []
  routes.forEach(route => {
    const tmp = {
      ...route,
      meta: {
        activeMenu: activeNav,
        id: route.id,
        aside: level === 2 ? routes.map(item => {
          return {
            title: item.menuName,
            name: item.name,
            hidden: item.hidden,
            menuIcon: item.menuIcon
          }
        }) : aside,
        topAside: level === 3 ? routes.map(item => {
          return {
            title: item.menuName,
            name: item.name,
            hidden: item.hidden,
            menuIcon: item.menuIcon
          }
        }) : []
      }
    }
    if (tmp.children && tmp.children.length) {
      let childrenBaseUrl = ''
      if (baseUrl === '') {
        childrenBaseUrl = tmp.path
      } else if (tmp.path !== '') {
        childrenBaseUrl = `${baseUrl}/${tmp.path}`
      }

      let tmpRoute = deepClone(route)
      tmpRoute.path = childrenBaseUrl

      tmpRoute.redirect = {
        name: tmp.children[0].name
      }
      delete tmpRoute.children
      delete tmp.child
      res.push(tmpRoute)
      let childrenRoutes = flatAsyncRoutes(tmp.children, [], childrenBaseUrl, activeNav, tmp.meta.aside, level + 1)
      childrenRoutes.map(item => {
        // 如果 path 一样则覆盖，因为子路由的 path 可能设置为空，导致和父路由一样，直接注册会提示路由重复
        if (res.some(v => v.path === item.path)) {
          res.forEach((v, i) => {
            if (v.path === item.path) {
              res[i] = item
            }
          })
        } else {
          res.push(item)
        }
      })

    } else {
      if (baseUrl !== '') {
        if (tmp.path !== '') {
          tmp.path = `${baseUrl}/${tmp.path}`
        } else {
          tmp.path = baseUrl
        }
      }
      res.push(tmp)
    }
  })
  return res
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = routes
  }
}

const actions = {
  // 获取菜单
  getRoutes({commit}) {
    return new Promise((resolve, reject) => {
      let menuKeys = getCookie('menuKeys') ? getCookie('menuKeys').split(',') : [];
      let routerDatas = [];
      menuKeys.forEach((item, index) => {
        routerDatas = [...routerDatas, getCookie(item) ? JSON.parse(getCookie(item)) : [] || []]
      })
      resolve(routerDatas)
    })
  },
  generateRoutes({commit}, routeDatas) {
    return new Promise(resolve => {
      let compRouterDatas = compAsyncRoutes(routeDatas)

      let newDatas = compRouterDatas.map(item => {
        item.path = `/${item.path}`
        if (item.children) {
          item.children = flatAsyncRoutes(item.children, [], '', item.path, item, 2)
          delete item.child
        }
        if (item.children && item.children.length) {
          item.redirect = {
            name: item.children[0].name
          }
        }

        return item
      })

      newDatas.push({path: '*', redirect: '/404', hidden: true})
      commit('SET_ROUTES', newDatas)
      console.log(newDatas)
      resolve(newDatas)
    })
  },
  resetRoutes({commit}) {
    resetRouter()
    commit('SET_ROUTES', [])
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}